package com.imooc.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.github.benmanes.caffeine.cache.Cache;
import com.google.gson.Gson;
import com.imooc.base.BaseInfoProperties;
import com.imooc.bo.*;
import com.imooc.enums.ActiveTime;
import com.imooc.enums.EduEnum;
import com.imooc.pojo.*;
import com.imooc.result.GraceJSONResult;
import com.imooc.result.ResponseStatusEnum;
import com.imooc.service.ResumeService;
import com.imooc.utils.GsonUtils;
import com.imooc.utils.PagedGridResult;
import com.imooc.vo.ResumeVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author liansen
 * @create 02-24-15:21
 */
@RestController
@RequestMapping("/resume")
public class ResumeController extends BaseInfoProperties {

    @Value("${server.port}")
    private String port;

    @Autowired
    private ResumeService resumeService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private Cache<String, Object> resumeRefreshCountsCache;

    @PostMapping("/init")
    public GraceJSONResult initResume(@RequestParam("userId") String userId){
        //因为userId是用户注册后生成userId传递过来的，所以这里不必判空
        resumeService.initResume(userId);
        return GraceJSONResult.ok();
    }

    /**
     * 根据用户id查询简历信息
     * @param userId
     * @return
     */
    @PostMapping("/queryMyResume")
    public GraceJSONResult queryMyResume(@RequestParam("userId") String userId){

        String resumeJson = redisTemplate.opsForValue().get(REDIS_RESUME_INFO + ":" + userId);
        ResumeVO resumeVO = null;
        if(StringUtils.isNotBlank(resumeJson)){
            resumeVO = new Gson().fromJson(resumeJson, ResumeVO.class);
        }else {

            resumeVO = resumeService.getResume(userId);
            if(resumeVO != null){
                redisTemplate.opsForValue().set(REDIS_RESUME_INFO + ":" + userId, new Gson().toJson(resumeVO));
            }else {
                //防止缓存穿透
                redisTemplate.opsForValue().set(REDIS_RESUME_INFO + ":" + userId, "{}", 10 *60, TimeUnit.SECONDS);
            }
        }
        return GraceJSONResult.ok(resumeVO);
    }


    /**
     * 更新我的优势
     * @param editResumeBO
     * @return
     */
    @PostMapping("/modify")
    public GraceJSONResult modify(@RequestBody @Valid EditResumeBO editResumeBO) {
        resumeService.editResume(editResumeBO);
        redisTemplate.delete(REDIS_RESUME_INFO + ":" + editResumeBO.getUserId());
        return GraceJSONResult.ok();
    }

    /**
     * 新增/编辑工作经验
     */
    @PostMapping("/editWorkExp")
    public GraceJSONResult editWorkExp(@RequestBody EditWorkExpBO editWorkExpBO){
        resumeService.editResumeWork(editWorkExpBO);
        redisTemplate.delete(REDIS_RESUME_INFO + ":" + editWorkExpBO.getUserId());
        return GraceJSONResult.ok();
    }

    /**
     * 查询工作经验
     */
    @PostMapping("/getWorkExp")
    public GraceJSONResult getWorkExp(@RequestParam("workExpId") String workExpId, @RequestParam("userId") String userId){
        ResumeWorkExp resumeWorkExp = resumeService.getWorkExp(workExpId, userId);
        return GraceJSONResult.ok(resumeWorkExp);
    }

    /**
     * 删除工作经验
     */
    @PostMapping("/deleteWorkExp")
    public GraceJSONResult deleteWorkExp(@RequestParam("workExpId") String workExpId, @RequestParam("userId") String userId){
        resumeService.deleteWorkExp(workExpId, userId);
        redisTemplate.delete(REDIS_RESUME_INFO + ":" + userId);
        return GraceJSONResult.ok();
    }

    /**
     * 新增/编辑项目经验
     */
    @PostMapping("/editProjectExp")
    public GraceJSONResult getWorkExp(@RequestBody EditProjectExpBO editProjectExpBO){
        resumeService.editProjectExp(editProjectExpBO);
        redisTemplate.delete(REDIS_RESUME_INFO + ":" + editProjectExpBO.getUserId());
        return GraceJSONResult.ok();
    }

    /**
     * 查询项目经验
     */
    @PostMapping("/getProjectExp")
    public GraceJSONResult getProjectExp(@RequestParam("projectExpId") String projectExpId, @RequestParam("userId") String userId){
        ResumeProjectExp resumeProjectExp = resumeService.getProjectExp(projectExpId, userId);
        return GraceJSONResult.ok(resumeProjectExp);
    }

    /**
     * 删除项目经验
     */
    @PostMapping("/deleteProjectExp")
    public GraceJSONResult deleteProjectExp(@RequestParam("projectExpId") String projectExpId, @RequestParam("userId") String userId){
        resumeService.deleteProjectExp(projectExpId, userId);
        redisTemplate.delete(REDIS_RESUME_INFO + ":" + userId);
        return GraceJSONResult.ok();
    }

    /**
     * 新增/编辑教育经历
     */
    @PostMapping("/editEducation")
    public GraceJSONResult editEducation(@RequestBody EditEducationBO editEducationBO){
        resumeService.editEducation(editEducationBO);
        redisTemplate.delete(REDIS_RESUME_INFO + ":" + editEducationBO.getUserId());
        return GraceJSONResult.ok();
    }

    /**
     * 查询教育经历
     */
    @PostMapping("/getEducation")
    public GraceJSONResult getEducation(@RequestParam("eduId") String eduId, @RequestParam("userId") String userId){
        ResumeEducation resumeEducation = resumeService.getEducation(eduId, userId);
        return GraceJSONResult.ok(resumeEducation);
    }

    /**
     * 删除教育经历
     */
    @PostMapping("/deleteEducation")
    public GraceJSONResult deleteEducation(@RequestParam("eduId") String eduId, @RequestParam("userId") String userId){
        resumeService.deleteEducation(eduId, userId);
        redisTemplate.delete(REDIS_RESUME_INFO + ":" + userId);
        return GraceJSONResult.ok();
    }

    /**
     * 新增/编辑 求职期望
     */
    @PostMapping("/editJobExpect")
    public GraceJSONResult editJobExpect(@RequestBody EditResumeExpectBO editResumeExpectBO){
        resumeService.editJobExpect(editResumeExpectBO);
        redisTemplate.delete(REDIS_RESUME_EXPECT + ":" + editResumeExpectBO.getUserId());
        return GraceJSONResult.ok();
    }

    /**
     * 查询求职期望
     */
    @PostMapping("/getMyResumeExpectList")
    public GraceJSONResult getMyResumeExpectList(String resumeId, String userId){
        String resumeExceptJson = redisTemplate.opsForValue().get(REDIS_RESUME_EXPECT + ":" + userId);
        List<ResumeExpect> resumeExpectList;
        if(StringUtils.isNotBlank(resumeExceptJson)){
            resumeExpectList = GsonUtils.stringToList(resumeExceptJson, ResumeExpect.class);
        }else {
            resumeExpectList = resumeService.getMyResumeExpectList(resumeId, userId);
            if(CollectionUtils.isEmpty(resumeExpectList)){
                redisTemplate.opsForValue().set(REDIS_RESUME_EXPECT + ":" + userId, "[]", 10 * 60, TimeUnit.SECONDS);
            }
            redisTemplate.opsForValue().set(REDIS_RESUME_EXPECT + ":" + userId, GsonUtils.object2String(resumeExpectList));
        }
        return GraceJSONResult.ok(resumeExpectList);
    }

    /**
     * 删除求职期望
     */
    @PostMapping("/deleteMyResumeExpect")
    public GraceJSONResult deleteMyResumeExpect(@RequestParam("resumeExpectId") String resumeExpectId, @RequestParam("userId") String userId){
        resumeService.deleteMyResumeExpect(resumeExpectId, userId);
        redisTemplate.delete(REDIS_RESUME_EXPECT + ":" + userId);
        return GraceJSONResult.ok();
    }


    /**
     * 刷新简历
     * @param userId
     * @param resumeId
     * @return
     */
    @PostMapping("/refresh")
    public GraceJSONResult refresh(@RequestParam("userId") String userId, @RequestParam("resumeId") String resumeId){

        /**
         * 1. 判断最新的次数是不是比设定的简历刷新的最大次数还大，如果超出了设定的最大次数，则提示友好信息
         * 2. 如果比设定的最大次数小,则在原来的次数上加1，将结果保存进redis
         * 3. 用户每天最多刷新最大次数，所以redis的值每天要重置
         */

        //获取数据库中设定的简历最大刷新次数
        //TODO 后面会改为其他中间件

        /**
         * 如果本地缓存Caffeine中没有数据,就会从redis中获取,因为在SysParamConfig中做了缓存预热，
         * 所以本服务启动后就已经从mysql中查到最大次数加载进了redis;
         */
        int maxCounts = (int) resumeRefreshCountsCache.get(CACHE_MAX_RESUME_REFRESH_COUNTS, s -> {
            String maxCountsStr = redisTemplate.opsForValue().get(REDIS_MAX_RESUME_REFRESH_COUNTS);
            return Integer.parseInt(maxCountsStr);
        });


        //从redis中获取用户当天已经刷新了的次数
        String today = LocalDate.now().toString(); // yyyy-MM-dd

        int userAlreadyRefreshedCounts = 0;


        String userAlreadyRefreshedCountsStr = redisTemplate.opsForValue().get(USER_ALREADY_REFRESHED_COUNTS + ":" + today + ":" + userId);

        if(StringUtils.isBlank(userAlreadyRefreshedCountsStr)){
            /**
             * 如果为空，则表示用户今天还未刷新简历,直接将次数设置为0,存进redis即可，
             * 用户每天都有最大的刷新次数，所以设置过期时间为24小时;
             */
            redisTemplate.opsForValue().set(USER_ALREADY_REFRESHED_COUNTS + ":" + today + ":" + userId, "0", 24*60*60, TimeUnit.SECONDS);
        }else {
            //不为空， 则获取次数，转为int
            userAlreadyRefreshedCounts = Integer.parseInt(userAlreadyRefreshedCountsStr);
        }

        if(userAlreadyRefreshedCounts < maxCounts){
            //用户刷新简历
            refreshResume(userId, resumeId);
            //将次数加 1, 存进redis中
            redisTemplate.opsForValue().increment(USER_ALREADY_REFRESHED_COUNTS + ":" + today + ":" + userId, 1);
        }else {
            return GraceJSONResult.errorCustom(ResponseStatusEnum.RESUME_MAX_LIMIT_ERROR);
        }

        return GraceJSONResult.ok();
    }

    private void refreshResume(String userId, String resumeId) {
        Resume resume = new Resume();
        resume.setId(resumeId);
        resume.setUserId(userId);
        resume.setRefreshTime(LocalDateTime.now());
        resume.setUpdatedTime(LocalDateTime.now());
        resumeService.update(resume, new LambdaQueryWrapper<Resume>()
                .eq(Resume::getId, resumeId)
                .eq(Resume::getUserId, userId));
        redisTemplate.delete(REDIS_RESUME_INFO + ":" + userId);
    }

    /**
     * 八表联查
     */
    @PostMapping("/searchResumes")
    public GraceJSONResult searchResumes(@RequestBody SearchResumesBO searchResumesBO, Integer page, Integer limit){

        String activeTime = searchResumesBO.getActiveTime();
        Integer activeTimes = ActiveTime.getActiveTimes(activeTime);
        searchResumesBO.setActiveTimes(activeTimes);

        String edu = searchResumesBO.getEdu();
        Integer eduIndex = EduEnum.getEduIndex(edu);
        List<String> eduList = EduEnum.getEduList(eduIndex);
        searchResumesBO.setEduList(eduList);

        PagedGridResult gridResult = resumeService.searchResumes(searchResumesBO,
                page,
                limit);

        return GraceJSONResult.ok(gridResult);
    }

}

